import { defineComponent, ref, computed, onMounted, onUnmounted, watch } from 'vue'
import './index.module.scss';

export default defineComponent({
  name: 'RulerProgress',
  props: {
    // 当前值
    value: {
      type: Number,
      default: 0
    },
    // 最大值
    max: {
      type: Number,
      default: 100
    },
    // 刻度间隔
    step: {
      type: Number,
      default: 10
    },
    // 多少刻度为一个大区间
    stepArea: {
      type: Number,
      default: 5
    },
    // 刻度高度比例 (0-1)
    tickHeightRatio: {
      type: Number,
      default: 0.2
    },
    // 主刻度高度比例 (0-1)
    majorTickHeightRatio: {
      type: Number,
      default: 0.3
    },
    // 颜色
    color: {
      type: String,
      default: '#409eff'
    },
    bufferTicks: {
      type: Number,
      default: 5
    },
    /** 是否显示刻度尺调节条 */
    showRange: {
      type: Boolean,
      default: false
    },
    videoElement: {
      type: HTMLVideoElement,
      default: null
    },
    showAudio: {
      type: Boolean,
      default: false
    },
    waveformColor: {
      type: String,
      default: '#FFAE0D'
    }
  },
  setup(props, { emit }) {
    // 计算当前进度位置
    const progressPosition = computed(() => {
      return (props.value / props.max) * 100
    })

    const rulerRef = ref<HTMLElement | null>(null)
    const rulerWidth = ref(0)
    const scrollLeft = ref(0)
    const isDragging = ref(false)

    // 计算总刻度数量
    const tickCount = computed(() => Math.ceil(props.max / props.step))

    // 计算每像素对应的值
    const valuePerPixel = computed(() => props.max / rulerWidth.value)

    // 计算当前可见区域的起始和结束索引（优化性能）
    const visibleRange = computed(() => {
      if (!rulerRef.value) return { start: 0, end: 0 }
      const containerWidth = rulerRef.value.clientWidth
      const startValue = Math.max(0, scrollLeft.value * valuePerPixel.value)
      const endValue = startValue + containerWidth * valuePerPixel.value
      const startIndex = Math.floor(startValue / props.step) - props.bufferTicks
      const endIndex = Math.ceil(endValue / props.step) + props.bufferTicks
      return {
        start: Math.max(0, startIndex),
        end: Math.min(tickCount.value, endIndex)
      }
    })
    watch(progressPosition, value => {
      if (value === 100) {
        emit('playend')
      }
    })
    const methods = {
      // 处理滚动事件
      handleScroll() {
        if (rulerRef.value) {
          scrollLeft.value = rulerRef.value.scrollLeft
        }
      },
      // 更新尺子宽度
      updateRulerWidth() {
        if (rulerRef.value) {
          rulerWidth.value = rulerRef.value.clientWidth
        }
      },
      // 处理点击或拖动
      handlePointerDown(e: PointerEvent) {
        isDragging.value = true
        methods.updateValueFromEvent(e)
        document.addEventListener('pointermove', methods.handlePointerMove)
        document.addEventListener('pointerup', methods.handlePointerUp)
      },
      handlePointerMove(e: PointerEvent) {
        if (isDragging.value) {
          methods.updateValueFromEvent(e)
        }
      },
      handlePointerUp() {
        isDragging.value = false
        document.removeEventListener('pointermove', methods.handlePointerMove)
        document.removeEventListener('pointerup', methods.handlePointerUp)
      },
      updateValueFromEvent(e: PointerEvent) {
        if (!rulerRef.value) return
        const rect = rulerRef.value.getBoundingClientRect()
        const offsetX = e.clientX - rect.left
        const percentage = Math.min(1, Math.max(0, offsetX / rect.width))
        const newValue = Math.round(percentage * props.max)
        emit('update:value', newValue)
        emit('change', newValue)
      }
    }
    onMounted(() => {
      methods.updateRulerWidth()
      window.addEventListener('resize', methods.updateRulerWidth)
    })

    onUnmounted(() => {
      window.removeEventListener('resize', methods.updateRulerWidth)
      document.removeEventListener('pointermove', methods.handlePointerMove)
      document.removeEventListener('pointerup', methods.handlePointerUp)
    })
    // 区间控制相关状态
    const rangeControlRef = ref<HTMLElement | null>(null);
    const isRangeDragging = ref(false);
    const rangeStart = ref(0); // 区间起始百分比 (0-100)
    const rangeEnd = ref(100); // 区间结束百分比 (0-100)
    const activeRangeHandle = ref<'start' | 'end' | 'middle' | null>(null);

    // 计算当前显示范围的实际值
    const visibleRangeValues = computed(() => ({
      start: (rangeStart.value / 100) * props.max,
      end: (rangeEnd.value / 100) * props.max
    }));
    watch(progressPosition, val => {
      if (props.showRange) {
        rangeStart.value = val;
        rangeEnd.value = rangeStart.value + 25;
      }
    })
    // 区间控制方法
    const rangeMethods = {
      handleRangePointerDown(e: PointerEvent, handleType: 'start' | 'end' | 'middle') {
        e.stopPropagation();
        activeRangeHandle.value = handleType;
        isRangeDragging.value = true;
        document.addEventListener('pointermove', rangeMethods.handleRangePointerMove);
        document.addEventListener('pointerup', rangeMethods.handleRangePointerUp);
      },

      handleRangePointerMove(e: PointerEvent) {
        if (!isRangeDragging.value || !rulerRef.value) return;
        const rect = rulerRef.value.getBoundingClientRect();
        const offsetX = e.clientX - rect.left;
        const percentage = Math.min(1, Math.max(0, offsetX / rect.width)) * 100;
        if (activeRangeHandle.value === 'start') {
          rangeStart.value = Math.min(percentage, rangeEnd.value - 5); // 最小保留5%的区间
        } else if (activeRangeHandle.value === 'end') {
          rangeEnd.value = Math.max(percentage, rangeStart.value + 5); // 最小保留5%的区间
        } else if (activeRangeHandle.value === 'middle') {
          const rangeWidth = rangeEnd.value - rangeStart.value;
          const newStart = Math.max(0, Math.min(100 - rangeWidth, percentage - rangeWidth / 2));
          rangeStart.value = newStart;
          rangeEnd.value = newStart + rangeWidth;
        }
      },
      handleRangePointerUp() {
        isRangeDragging.value = false;
        activeRangeHandle.value = null;
        document.removeEventListener('pointermove', rangeMethods.handleRangePointerMove);
        document.removeEventListener('pointerup', rangeMethods.handleRangePointerUp);
      },
      resetRange() {
        rangeStart.value = 0;
        rangeEnd.value = 100;
      }
    };
    /**
     * renderTicks以支持区间缩放
     * @returns
     */
    const renderTicks = () => {
      const ticks = [];
      const { start, end } = visibleRange.value;
      const visibleStartValue = visibleRangeValues.value.start;
      const visibleEndValue = visibleRangeValues.value.end;
      for (let i = start; i <= end; i++) {
        const value = i * props.step;
        // 只渲染在可见区间内的刻度
        if (value < visibleStartValue || value > visibleEndValue) continue;
        // 计算在可见区间内的相对位置
        const position = ((value - visibleStartValue) / (visibleEndValue - visibleStartValue)) * 100;
        const isMajorTick = value % (props.step * props.stepArea) === 0;
        ticks.push(
          <div
            key={`tick-${i}`}
            class={[
              'ruler-tick',
              isMajorTick ? 'major-tick' : ''
            ]}
            style={{
              left: `${position}%`,
              height: `${isMajorTick ? props.majorTickHeightRatio * 100 : props.tickHeightRatio * 100}%`
            }}
          >
            {isMajorTick && (
              <span class='tick-label'>{value}</span>
            )}
          </div>
        );
      }
      return ticks;
    };
    /**
     * 渲染区间控制条
     * @returns
     */
    const renderRangeControl = () => (
      <div class='range-control' ref={rangeControlRef}>
        <div class='range-track' />
        <div
          class='range-handle range-handle-start'
          style={{ left: `${rangeStart.value}%` }}
          onPointerdown={(e) => rangeMethods.handleRangePointerDown(e, 'start')}
        />
        <div
          class='range-handle range-handle-end'
          style={{ left: `${rangeEnd.value}%` }}
          onPointerdown={(e) => rangeMethods.handleRangePointerDown(e, 'end')}
        />
        <div
          class='range-area'
          style={{
            left: `${rangeStart.value}%`,
            width: `${rangeEnd.value - rangeStart.value}%`
          }}
          onPointerdown={(e) => rangeMethods.handleRangePointerDown(e, 'middle')}
        />
        <el-button class='range-reset' size='mini' onClick={rangeMethods.resetRange}>
          重置
        </el-button>
      </div>
    );

    return () => (
      <div class='ruler-container'>
        {/* 区间控制条 */}
        {props.showRange && renderRangeControl()}
        <div
          ref={rulerRef}
          class='ruler'
          onPointerdown={methods.handlePointerDown}
          onScroll={methods.handleScroll}
        >
          <div
            class='ruler-placeholder'
            style={{ width: `${(props.max / props.step) * 2}px` }}
          />
          <div class='ruler-track' />
          <div
            class='ruler-progress'
            style={{
              width: `${progressPosition.value}%`,
              backgroundColor: props.color
            }}
          />
          {/* 刻度线 */}
          {renderTicks()}
        </div>
      </div>
    )
  }
})
